package com.mz.mattress.client.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.mz.mattress.api.common.Constants;
import com.mz.mattress.api.common.Result;
import com.mz.mattress.api.entity.*;
import com.mz.mattress.api.enums.CouponSendTypeEnum;
import com.mz.mattress.api.jwt.ClientJwt;
import com.mz.mattress.api.jwt.JwtTokenUtil;
import com.mz.mattress.api.resp.UserAuth;
import com.mz.mattress.api.util.*;
import com.mz.mattress.client.api.req.*;
import com.mz.mattress.client.api.resp.RegisterResp;
import com.mz.mattress.client.common.FailMessage;
import com.mz.mattress.client.common.Holder;
import com.mz.mattress.client.interceptor.GlobalExecutor;
import com.mz.mattress.client.mapper.*;
import com.mz.mattress.client.service.*;
import com.mz.mattress.client.util.WxQrcodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * 会员服务 hello1
 */
@Service
@Slf4j
public class MemberServiceImpl implements MemberService {

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private WxQrcodeUtil wxQrcodeUtil;

    @Autowired
    private MemberLoginLogMapper memberLoginLogMapper;

//    @Autowired
//    private SmsService smsService;

    @Resource(name = "clientWxMaService")
    private WxMaService clientWxMaService;

    @Autowired
    private CouponService couponService;

    @Autowired
    private CouponSendRecordService couponSendRecordService;

    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public Result<UserAuth> WxLogin(WxLoginReq wxLoginReq, String ip) {

        String code = wxLoginReq.getCode();
        UserInfo userInfo = wxLoginReq.getUserInfo();
        if (code == null || userInfo == null) {
            return Result.fail(FailMessage.BAD_ARGUMENT);
        }

        String sessionKey = null;
        String openId = null;
        try {
            WxMaJscode2SessionResult result = this.clientWxMaService.getUserService().getSessionInfo(code);
            sessionKey = result.getSessionKey();
            openId = result.getOpenid();
            userInfo.setOpenid(openId);
            log.info("openId={}", openId);
        } catch (Exception e) {
            log.info("getSessionInfo_error", e);
        }

        if (sessionKey == null || openId == null) {
            log.error("invoke_weixin_fail,code={}", code);
            return Result.fail(FailMessage.WX_INVOKE_FAIL);
        }

        List<Member> users = memberMapper.selectList(new LambdaQueryWrapper<Member>().
                eq(Member::getOpenId, openId));

        String mobile = null;
        Long memberId = null;
        if (users == null || users.size() == 0) {
            //注册新用户
            memberId = IdUtil.getMemberId();

            Member user = new Member();
            user.setId(memberId);
            user.setOpenId(openId);
            user.setSessionKey(sessionKey);
            user.setAvatar(userInfo.getAvatarUrl());
            user.setNickname(userInfo.getNickName());
            user.setStatus(0);
            memberMapper.insert(user);

            //TODO 发放优惠券
            couponService.sendCoupon(memberId, CouponSendTypeEnum.NEW_REGISTER);

        } else {

            if (users.size() > 1) {
                log.error("openid_error,openid={}", openId);
                return Result.fail(FailMessage.OPENID_ERROR);
            }

            //更新最后登录信息
            Member member = users.get(0);
            mobile = member.getMobile();
            memberId = member.getId();

            //更新sessionkey
            Member user = new Member();
            user.setId(memberId);
            user.setSessionKey(sessionKey);
            memberMapper.updateById(user);

            //检查新注册的手机号，是否有未领取的优惠券，有则发放 异步发优惠券
            GlobalExecutor.executeByCommon(() -> {
                couponSendRecordService.loadByMobile(member.getMobile());
            });

        }

        insertLoginLog(memberId, ip);

        ClientJwt clientJwt = new ClientJwt();
        clientJwt.setOpenId(openId);
        clientJwt.setSessionKey(sessionKey);
        clientJwt.setMemberId(memberId);
        clientJwt.setMobile(mobile);

        String token = JwtTokenUtil.createClientToken(clientJwt);
        UserAuth userAuth = new UserAuth();
        userAuth.setToken(token);
        userAuth.setMobile(mobile);
        return Result.ok(userAuth);
    }

    @Override
    public Result<RegisterResp> bindWxMobile(String sessionkey, String data, Long memberId) {

        String mobile = null;
        try {
            //{"errMsg":"getPhoneNumber:fail:user cancel"}
            if (data == null) {
                log.info("data=null,bindWxMobile");
                return Result.fail();
            }
            JsonNode jsonNode = JacksonUtils.toObj(data);
            if (jsonNode.get("encryptedData") == null || jsonNode.get("iv") == null) {
                return Result.fail();
            }

            String encryptedData = jsonNode.get("encryptedData").textValue();
            String iv = jsonNode.get("iv").textValue();

            log.info("encryptedData={},iv={}", encryptedData, iv);

            //获取用户绑定微信的手机号
            WxMaPhoneNumberInfo phoneNumberInfo = clientWxMaService.getUserService().getPhoneNoInfo(sessionkey, encryptedData, iv);
            mobile = phoneNumberInfo.getPhoneNumber();
        } catch (Exception e) {
            log.error("bindMobile_wx_fail,data=" + data);
            e.printStackTrace();
            return Result.fail();
        }

        return bindMobile(mobile, memberId);
    }

    @Override
    public Result<UserAuth> reLogin() {

        ClientJwt clientJwt = Holder.CLIENT_JWT_THREAD_LOCAL.get();
        String mobile = clientJwt.getMobile();

        ClientJwt newJwt = new ClientJwt();
        newJwt.setOpenId(clientJwt.getOpenId());
        newJwt.setSessionKey(clientJwt.getSessionKey());
        newJwt.setMemberId(clientJwt.getMemberId());
        newJwt.setMobile(mobile);

        String token = JwtTokenUtil.createClientToken(clientJwt);
        UserAuth userAuth = new UserAuth();
        userAuth.setToken(token);
        userAuth.setMobile(mobile);

        return Result.ok(userAuth);
    }

    private Result<RegisterResp> bindMobile(String mobile, Long memberId) {

        // 检查手机号是否已注册
        Long count = memberMapper.selectCount(new LambdaQueryWrapper<Member>().
                eq(Member::getMobile, mobile));
        if (count > 0) {
            log.error("mobile_has_registered,mobile={}", mobile);
            return Result.fail(FailMessage.AUTH_MOBILE_REGISTERED);
        }

        Member member = memberMapper.selectById(memberId);
        if (member == null) {
            log.error("member=null,memberId={}", memberId);
            return Result.fail(FailMessage.NOT_FIND_MEMBER);
        }

        ClientJwt clientJwt = Holder.CLIENT_JWT_THREAD_LOCAL.get();
        clientJwt.setMobile(mobile);

        String token = JwtTokenUtil.createClientToken(clientJwt);

        Member update = new Member();
        update.setId(memberId);
        update.setMobile(mobile);
        memberMapper.updateById(update);

        //检查新注册的手机号，是否有未领取的优惠券，有则发放 异步发优惠券
        GlobalExecutor.executeByCommon(() -> {
            couponSendRecordService.loadByMobile(mobile);
        });

        RegisterResp resp = new RegisterResp();
        resp.setMobile(mobile);
        resp.setToken(token);

        return Result.ok(resp);
    }

    private void insertLoginLog(Long memberId, String ip) {
        MemberLoginLog loginLog = new MemberLoginLog();
        loginLog.setMemberId(memberId);
        loginLog.setIp(ip);
        loginLog.setClient(1);
        memberLoginLogMapper.insert(loginLog);
    }

    @Override
    public Result updateById(MemberReq req) {

        Long memberId = req.getMemberId();

        Member member = memberMapper.selectById(memberId);
        if (member == null) {
            return Result.fail(FailMessage.NOT_FIND_MEMBER);
        }

        if (req.getAvatar() != null ||
                req.getNickname() != null ||
                req.getSex() != null ||
                req.getBirthday() != null ||
                req.getWeight() != null) {
            Member update = new Member();
            update.setId(memberId);
            update.setNickname(req.getNickname());
            update.setAvatar(req.getAvatar());
            update.setSex(req.getSex());
            update.setBirthday(req.getBirthday());
            update.setWeight(req.getWeight());
            memberMapper.updateById(update);
        }

        return Result.ok();
    }

    @Override
    public Result<Member> getById(Long memberId) {

        Member member = memberMapper.selectById(memberId);
        if (member == null) {
            return Result.fail("请先登录");
        }
        return Result.ok(member);
    }

    @Override
    public Result qrcode(Long memberId) {

        String code = InviteCodeUtils.idToCode(memberId);
        String scene = "inviteCode=" + code;
        String data = wxQrcodeUtil.generateQrcode(scene, Constants.DEFAULT_PAGE, 200);

        if (data == null) {
            return Result.fail();
        }
        return Result.ok(data);
    }

    @Override
    public void saveDeviceInfo(Long memberId, String deviceCode) {

        Device device = deviceMapper.selectByDeviceCode(deviceCode);
        if (device == null || device.getMemberId() == null) {
            return;
        }

        Member update = new Member();
        update.setId(memberId);
        update.setLastMerchantId(device.getMerchantId());
        update.setLastMerchantName(device.getMerchantName());
        memberMapper.updateById(update);

    }

}
